home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************
- * PlaySound.c
- * This routine sets up an ioRequest and plays back a waveform through the
- * Amiga audio hardware
- *
- * Usage : PlaySound(buffer,repeat,period,volume)
- * buffer is a pointer to a waveform
- * repeat is the number of times to play the wave (0 == forever)
- * period determines the playback rate (minimum value == 124)
- * volume goes from 0 to 64
- *****************************************************************************/
-
- #include "exec/types.h"
- #include "devices/audio.h"
- #include "exec/memory.h"
-
- #define LEFT0F 1
- #define RIGHT0F 2
- #define RIGHT1F 4
- #define LEFT1F 8
- #define SIGBREAKF_CTRL_C (1<<12)
-
- extern struct MsgPort *CreatePort();
- struct IOAudio *AllocMem();
-
- /* Look for a left channel, then a right */
- UBYTE allocationMap[] = { LEFT0F, LEFT1F, RIGHT0F, RIGHT1F };
-
- /*****************************************************************************
- * Purpose: To allocate and initialize an IO Request Block. *
- *****************************************************************************/
-
- SetIOA(per, vol, repeat, len, ioa)
- LONG per, vol, repeat;
- ULONG len;
- struct IOAudio **ioa;
- {
- struct MsgPort *port;
-
- /* Allocate IOAudio structure */
- (*ioa) = AllocMem(sizeof(struct IOAudio), MEMF_PUBLIC | MEMF_CLEAR);
-
- /* If Allocation Successful ... */
- if (*ioa)
- {
- /* Set Priority */
- (*ioa)->ioa_Request.io_Message.mn_Node.ln_Pri = 10;
- /* Create Message port for IORequest to talk to Amiga */
- if (!(port = CreatePort(NULL, 0)))
- {
- FreeMem((*ioa), sizeof(struct IOAudio));
- *ioa = NULL;
- }
- /* If Creation Successful ... */
- else
- {
- /* Get a channel */
- (*ioa)->ioa_Request.io_Message.mn_ReplyPort = port;
- (*ioa)->ioa_Data = allocationMap;
- (*ioa)->ioa_Length = sizeof(allocationMap);
- /* Open Audio Device for output */
- if(OpenDevice(AUDIONAME, 0, (*ioa), 0))
- {
- DeletePort(port);
- FreeMem((*ioa), sizeof(struct IOAudio));
- *ioa = NULL;
- }
- /* If open worked ... */
- else
- {
- /* Set Up Request */
- (*ioa)->ioa_Request.io_Flags = ADIOF_PERVOL;
- (*ioa)->ioa_Request.io_Command = CMD_WRITE;
- (*ioa)->ioa_Period = per;
- (*ioa)->ioa_Volume = vol;
-
- /* For some reason, the Audio chip can't play samples */
- /* longer than 131k, so we kludge. Oh, well. */
- if(len < 131000)
- (*ioa)->ioa_Cycles = repeat;
- else
- (*ioa)->ioa_Cycles = 1;
- }
- }
- }
- }
-
- /*****************************************************************************
- * Purpose: To play back a sound. *
- *****************************************************************************/
-
- struct IOAudio *PlaySound(buffer, buflen, repeat, period, volume)
- BYTE *buffer;
- ULONG buflen;
- LONG repeat,period,volume;
- {
- struct IOAudio *ioa;
- BYTE *DataPtr;
- ULONG PlayLen;
-
- DataPtr = buffer;
-
- /* Set Up IOAudio structure */
- SetIOA(period, volume, repeat, buflen, &ioa);
- if (!ioa)
- return(NULL);
-
- /* Set up data and length pointers of ioa */
- SetLength(&PlayLen, buflen, &DataPtr, ioa);
-
- /* Send command to Audio chip */
- BeginIO(ioa);
- repeat--;
-
- /* If no data remains to play, return ioa pointer */
- if(PlayLen == 0)
- return(ioa);
-
- /* If there is more (buflen > 131000), continue until there isn't */
- while(TRUE)
- {
- ULONG signals;
-
- /* Wait until current chunk is done */
- signals = Wait((1 << ioa->ioa_Request.io_Message.mn_ReplyPort->mp_SigBit) | SIGBREAKF_CTRL_C);
-
- if (signals & SIGBREAKF_CTRL_C)
- {
- SetSignal(SIGBREAKF_CTRL_C, SIGBREAKF_CTRL_C);
- return(ioa);
- }
-
- /* If more remains, continue */
- if(PlayLen > 0)
- {
- /* update pointers and start next chunk */
- FixLength(&PlayLen, &DataPtr, ioa);
- BeginIO(ioa);
- /* return if playing the last chunk for the last time */
- if((PlayLen == 0) && (repeat == 0))
- return(ioa);
- }
- /* If not ... */
- else
- {
- /* Check repeat counter */
- if(repeat != 0)
- {
- /* Restart wave */
- DataPtr = buffer;
- SetLength(&PlayLen, buflen, &DataPtr, ioa);
- BeginIO(ioa);
- if(repeat > 0)
- repeat--;
- }
- }
- }
- }
-
- /*****************************************************************************
- * Purpose: To stop and delete a sound. THIS IS THE CLEAN UP ROUTINE!! *
- *****************************************************************************/
-
- StopSound(struct IOAudio *ioa)
- {
- AbortIO(ioa);
- if(ioa->ioa_Request.io_Device)
- CloseDevice(ioa);
- if(ioa->ioa_Request.io_Message.mn_ReplyPort)
- DeletePort(ioa->ioa_Request.io_Message.mn_ReplyPort);
- if(ioa)
- FreeMem(ioa,sizeof(struct IOAudio));
- }
-
- /*****************************************************************************
- * Purpose: To set the length of the sound to be played. *
- *****************************************************************************/
-
- SetLength(ULONG *LenPtr, ULONG buflen, BYTE **DataHndl, struct IOAudio *ioa)
- {
- if(buflen <= 131000)
- (*LenPtr) = buflen;
- else
- (*LenPtr) = 131000;
-
- ioa->ioa_Length = (*LenPtr);
- ioa->ioa_Data = (*DataHndl);
-
- if((*LenPtr) != buflen)
- {
- (*LenPtr) = buflen - 131000;
- (*DataHndl) += 131000;
- }
- else
- (*LenPtr) = 0;
- }
-
- /*****************************************************************************
- * Purpose: To Check, if the full sound is to be played (or max 131000 bytes)*
- *****************************************************************************/
-
- FixLength(ULONG *LenPtr, BYTE **DataHndl, struct IOAudio *ioa)
- {
- if((*LenPtr) > 131000)
- {
- ioa->ioa_Length = 131000;
- ioa->ioa_Data = (*DataHndl);
- (*LenPtr) -= 131000;
- (*DataHndl) += 131000;
- }
- else
- {
- ioa->ioa_Length = (*LenPtr);
- ioa->ioa_Data = (*DataHndl);
- (*LenPtr) = 0;
- }
- }
-